﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using EECMISWS.WebProcessArgs;
using LogLib;
using Newtonsoft.Json.Linq;
using System.Threading;
using AppDataStruct;
using System.Reflection;
using HXService;

namespace EECMISWS
{
    internal partial class WSClient
    {
        public string BaseDirectory
        {
            get
            {
                return Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase).Substring(6);
            }
        }
        private string _strMessage = "";
        public string Message
        {
            get { return _strMessage; }
        }

        private string areaCode;
        public string AreaCode
        {
            get { return areaCode; }
            set { areaCode = value; }
        }

        /// <summary>
        /// 登录名称
        /// </summary>
        private string _userName;
        public string LoginName
        {
            get { return _userName; }
            set { _userName = value; }
        }

        /// <summary>
        /// 登录密码
        /// </summary>
        private string _password;
        public string PassWord
        {
            get { return _password; }
            set { _password = value; }
        }

        /// <summary>
        /// 接口会话ID
        /// </summary>
        private string _sessionID = "";
        public string SessionID
        {
            get { return _sessionID; }
            set { _sessionID = value; }
        }

        private WebClientConfig ClientConfig = new WebClientConfig();

        private WebReturnArgs _returnInfo = new WebReturnArgs();
        public WebReturnArgs WebResults
        {
            get
            {
                return _returnInfo;
            }
        }

        /// <summary>
        /// 核查是否是国家工作人员
        /// </summary>
        private const string funcCheckSpecialList = "kz_checkSpecialList";
      
        /// <summary>
        /// 核查是否是国家工作人员
        /// </summary>
        private const string funcQueryOfficial = "kz_queryOfficial";
    
        /// <summary>
        /// 是否在大陆境内
        /// </summary>
        private const string funcCheckInDomestic = "sq_checkInDomestic";
        
        /// <summary>
        /// 上传照片
        /// </summary>
        private const string funcSavePhoto = "sq_savePaperPhoto";

        public string XTMC
        {
            get;
            set;
        }

        private eecmisws webService = new eecmisws();

        private string _url = "";
        public string URL
        {
            get { return _url; }
            set { _url = value; }
        }

        private static object _lock = new object();

        private Dictionary<string, string> _forbiddenNations = new Dictionary<string, string>();

        private Dictionary<string, string> Nations = new Dictionary<string, string>();

        private bool _bInited = false;
        public bool Inited
        {
            get { return _bInited; }
        }

        public WSClient(string url)
        {
            _url = url;
            webService = new eecmisws();
            if (!string.IsNullOrEmpty(_url))
            {
                webService.Url = _url;
            }
        }
   
        public void OnQueryBegining()
        {
            Log.AddBeginningBoundary();
        }

        public void OnQueryEnding()
        {
            Log.AddEndingBoundary();
        }

        private void ResetWebServiceClient()
        {
            //if (webService.State == System.ServiceModel.CommunicationState.Opening
            //    || webService.State == System.ServiceModel.CommunicationState.Opened)
            //{
            //    try
            //    {
            //        Log.WriteAsync("开始执行中断Web服务连接");
            //        webService.Abort();
            //        Log.WriteAsync("中断Web服务连接成功!");
            //    }
            //    catch (Exception ex)
            //    {
            //        Log.WriteAsync("中断Web服务连接时发生了异常!\n");
            //        Log.WriteException(ex.ToString());
            //    }
                webService = null;
                Log.WriteAsync("重置Web服务连接...");
                webService = new eecmisws();
                if (!string.IsNullOrEmpty(_url))
                {
                    webService.Url = _url;
                }
                if (Login())
                {
                    Log.WriteAsync("重置连接后登录成功!");
                }
                else
                {
                    Log.WriteAsync("重置连接后登录失败!");
                }
            //}
        }

        public void ResetPersonInfo()
        {
            _returnInfo.Reset();
            _queryFrom = 0;
        }

        private bool LoadConfig()
        {
            try
            {              
                Log.WriteAsync("全国大集中接口服务地址: " + _url);
                ClientConfig.Load();
                if (string.IsNullOrEmpty(ClientConfig.TBDWBH) || string.IsNullOrEmpty(ClientConfig.CityCode))
                {
                    _strMessage = "填表单位编号或者区域代码为空";
                    return false;
                }
                _bInited = true;
                return true;
            }
            catch (Exception ex)
            {
                _strMessage = string.Format("WSClient配置加载错误:\n异常详情:{0}", ex.Message);
                Log.WriteException(ex.ToString());
                return false;
            }
        }

        private bool GetCertificateInfo(out string certSignData)
        {
            certSignData = "";
            try
            {
                string ret = HttpHelper.Post("http://127.0.0.1:7788/GetCertificateInfoPKCS7", "");
                if (!string.IsNullOrEmpty(ret))
                {
                    GetCertInfoReturnArg certInfo = JsonHandler.ConvertToJsonObject<GetCertInfoReturnArg>(ret);
                    if (1 == certInfo.success)
                    {
                        certSignData = certInfo.data;
                        return true;
                    }
                    else
                    {
                        Log.WriteAsync(string.Format("获取证书签名失败：{0}", certInfo.message));
                        return false;
                    }
                }
                else
                {
                    Log.WriteAsync("请求获取证书签名返回为空");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Log.WriteAsync(string.Format("获取证书签名异常：{0}", ex.ToString()));
                return false;
            }
        }

        private bool OnLogining()
        {
            string strLog;
            string certSignData = "";
            string strRet="!";
            try
            {
                //strRet = webService.login(_userName, _password);
                if (GetCertificateInfo(out certSignData))
                {

                    ////LogManage.WriteInfoLog("调用client.Url: " + client.Url + ", 用户名：" + loginInfo.OperateID + ",密码" + loginInfo.Password);
                    strRet = webService.loginNew(certSignData);
                    Log.WriteAsync(string.Format("调用航信登陆接口,返回{0}", strRet));
                }
            }
            catch (ThreadAbortException ex)
            {
                ResetWebServiceClient();
                Log.WriteAsync("登录时操作被中断");
                Log.WriteException(ex.ToString());
                return false;
            }
            catch (TimeoutException ex)
            {
                _strMessage = string.Format("登录服务器网络连接超时: {0}", ex.Message);
                Log.WriteException(ex.ToString());
                return false;
            }
            catch (System.ServiceModel.EndpointNotFoundException ex)
            {
                _strMessage = string.Format("无终结点监听...\n该错误通常是网络中断造成的，请检查网络是否连通.\n异常详情:{0}", ex.Message);
                Log.WriteException(ex.ToString());
                return false;
            }
            catch (Exception ex)
            {
                _strMessage = string.Format("登录服务器发生了异常.\n异常详情:{0}", ex.Message);
                Log.WriteException(ex.ToString());
                return false;
            }
            if (strRet.Contains("!"))
            {
                string strError = strRet;
                _strMessage = string.Format("登录服务器失败! 请检查探针程序是否运行正常\n原因:{0}", strError);
                strLog = string.Format("登录服务器失败，请检查探针程序是否运行正常:{0}, use {1}/{2}", strRet, _userName, _password);
                Log.WriteAsync(strLog);
                return false;
            }
            GetCertInfoReturnArg loginInfo = JsonHandler.ConvertToJsonObject<GetCertInfoReturnArg>(strRet);
            if (loginInfo.success !=1)
            {
                string strError = loginInfo.message;
                _strMessage = string.Format("登录服务器失败! \n原因:{0}", strError);
                strLog = string.Format("登录服务器失败:{0}, use {1}/{2}", strRet, _userName, _password);
                Log.WriteAsync(strLog);
                return false;
            }
            else
            {
                _sessionID = loginInfo.data;
                strLog = string.Format("登录服务器成功:{0},user:{1},psw:{2},SessionID:{3}", strRet, _userName, _password, _sessionID);
                Log.WriteAsync(strLog);
                return true;
            }
        }

        public bool Login()
        {
            if (!_bInited)
            {
                if (!LoadConfig())
                {
                    return false;
                }
            }
            bool bLogin = false;
            for (int i = 0; i < 3; i++)
            {
                if (OnLogining())
                {
                    bLogin = true;
                    break;
                }
                System.Threading.Thread.Sleep(200);
            }
            return bLogin;
        }

        /// <summary>
        /// 调用统一方法接口
        /// </summary>
        /// <param name="funccode">功能代码</param>
        /// <param name="args">参数集</param>
        /// <returns></returns>
        public WebReturnArgs CallUnimethod(string funccode, string args, bool containsData)
        {
            _strMessage = "";
            WebReturnArgs mReturn = new WebReturnArgs();
            try
            {
                string result = "";
                string exception = "";
                int i = 0;
                int tryCnt = 3;
                bool callSuccess = false;
                while (i < tryCnt)
                {
                    result = "";
                    if (CallUnimethod(funccode, args, ref result, out exception))
                    {
                        callSuccess = true;
                        break;
                    }
                    Thread.Sleep(200);
                }
                if (!callSuccess && !string.IsNullOrEmpty(exception))
                {
                    Log.WriteAsync("接口调用发生了异常: " + exception);
                    mReturn.CustomCode = 444;
                    mReturn.CallSuccessed = false;
                    mReturn.ExceptionString = exception;
                    _strMessage = exception;
                    return mReturn;
                }
                JObject jObj = JObject.Parse(result);
                mReturn.CallSuccessed = true;
                mReturn.ErrorCode = jObj["state"].ToString();
                mReturn.Message = jObj["message"].ToString();
                //接口操作成功
                if (jObj["success"].ToString() == "1")
                {
                    mReturn.Success = true;
                    if (containsData)
                    {
                        string strData = "";
                        try
                        {
                            strData = jObj["data"].ToString();
                        }
                        catch (System.Exception ex)
                        {
                            Log.WriteException(ex.ToString());
                        }
                        mReturn.DataContent = strData;
                    }
                    Log.WriteAsync("调用接口操作成功.");
                    return mReturn;
                }
                else  //接口操作失败
                {
                    if (mReturn.ErrorCode.Equals("CRJ1302") && funccode.Equals(funcQueryOfficial))
                    {
                        mReturn.Success = true;
                        mReturn.DataContent = "";
                    }
                    else
                    {
                        _strMessage = string.Format("操作失败: 错误代码{0}, 详情: {1}",
                            mReturn.ErrorCode,
                            mReturn.Message);
                        Log.WriteAsync(_strMessage);
                    }
                    return mReturn;
                }
            }
            catch (ThreadAbortException ex)
            {
                Log.WriteException(ex.ToString());
                return mReturn;
            }
            catch (System.Exception ex)
            {
                mReturn.CustomCode = 444;
                Log.WriteException(ex.ToString());
                _strMessage = "程序代码运行发生了异常: " + ex.Message;
                Log.WriteAsync(_strMessage);
                mReturn.CallSuccessed = false;
                mReturn.Success = false;
                mReturn.ExceptionString = _strMessage;
                return mReturn;
            }          
        }

        public bool CallUnimethod(string funccode, string args, ref string result, out string exception)
        {
            result = "";
            _strMessage = "";
            exception = "";
            string strLog = string.Format("开始调用统一接口方法:{0}. ", funccode);
            Log.WriteAsync(strLog);
            try
            {
                result = webService.unimethod(_sessionID, funccode, args);
            }
            catch (TimeoutException ex)
            {
                _strMessage = string.Format("eecmiswsPortTypeClient执行操作[{0}]时网络连接超时", funccode);
                exception = _strMessage;
                Log.WriteAsync(exception);
                return false;
            }
            catch (ThreadAbortException ex)
            {
                ResetWebServiceClient();
                _strMessage = string.Format("eecmiswsPortTypeClient执行操作[{0}]时线程中止.", funccode);
                exception = _strMessage;
                Log.WriteAsync(exception);
                return false;
            }
            catch (System.ServiceModel.EndpointNotFoundException ex)
            {
                _strMessage = exception = string.Format("无终结点监听...\n该错误通常是网络中断造成的，请检查网络是否连通.\n异常详情:{0}", ex.Message);
                exception = _strMessage;
                Log.WriteAsync(exception);
                return false;
            }
            catch (Exception ex)
            {
                _strMessage = exception = ex.ToString();
                exception = _strMessage;
                Log.WriteAsync(exception);
                return false;
            }
            finally
            {
                Log.WriteAsync("调用统一接口方法结束");
            }
            JObject jObj = JObject.Parse(result);
            string ErrorCode = jObj["state"].ToString();
            string Message = jObj["message"].ToString();
            string Success = jObj["success"].ToString();
            //接口操作成功
            if (Success == "1")
            {
                Log.WriteAsync("调用接口操作成功:" + funccode);
                return true;
            }
            if (ErrorCode.Equals("CRJ1302") && funccode.Equals(funcQueryOfficial))
            {
                return true;
            }
            if (ErrorCode.Equals("CRJ1002"))
            {
                if (Login())
                {
                    try
                    {
                        result = webService.unimethod(_sessionID, funccode, args);
                    }
                    catch (TimeoutException ex)
                    {
                        _strMessage = string.Format("eecmiswsPortTypeClient执行操作[{0}]时网络连接超时", funccode);
                        exception = _strMessage;
                        Log.WriteAsync(exception);
                        return false;
                    }
                    catch (ThreadAbortException ex)
                    {
                        ResetWebServiceClient();
                        _strMessage = string.Format("eecmiswsPortTypeClient执行操作[{0}]时线程中止.", funccode);
                        exception = _strMessage;
                        Log.WriteAsync(exception);
                        return false;
                    }
                    catch (System.ServiceModel.EndpointNotFoundException ex)
                    {
                        _strMessage = exception = string.Format("无终结点监听...\n该错误通常是网络中断造成的，请检查网络是否连通.\n异常详情:{0}", ex.Message);
                        exception = _strMessage;
                        Log.WriteAsync(exception);
                        return false;
                    }
                    catch (Exception ex)
                    {
                        _strMessage = exception = ex.ToString();
                        exception = _strMessage;
                        Log.WriteAsync(exception);
                        return false;
                    }
                    finally
                    {
                        Log.WriteAsync("再次调用统一接口方法结束");
                    }
                    //接口操作成功
                    if (Success == "1")
                    {
                        Log.WriteAsync("调用接口操作成功:" + funccode);
                        return true;
                    }
                    if (ErrorCode.Equals("CRJ1302") && funccode.Equals(funcQueryOfficial))
                    {
                        return true;
                    }
                    if (ErrorCode.Equals("CRJ1002"))
                    {
                        Log.WriteAsync("接口重新操作依然失败.");
                        return false;
                    }
                    return true;
                }
                else
                {
                    Log.WriteAsync("接口重新登录失败");
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 上传照片
        /// </summary>
        /// <param name="photoPath"></param>
        /// <param name="serialNumber"></param>
        /// <returns></returns>
        public bool SavePaperPhoto(string photoPath, string serialNumber)
        {
            _strMessage = "";
            byte[] bPic = Common.DatToByte(photoPath);
            if (bPic == null || bPic.Length == 0)
            {
                _strMessage = "文件数据为空";
                return false;
            }
            string strBase64string = Common.ByteToBase64String(bPic);
            if (string.IsNullOrEmpty(strBase64string.Trim()))
            {
                _strMessage = "Base64数据为空";
                return false;
            }
            ArgsUploadPhoto args = new ArgsUploadPhoto();
            args.xpbh = serialNumber;
            args.xpnr = strBase64string;
            args.xtmc = XTMC;
            string jsonData = JsonHandler.ConvertToJsonString(args);
            string strLog = string.Format("制证照片开始上传, 照片编号:{0}", args.xpbh);
            Log.WriteAsync(strLog);
            WebReturnArgs mReturn = CallUnimethod(funcSavePhoto, jsonData, false);
            if (mReturn.ErrorCode.Equals("CRJ1002") || mReturn.ErrorCode.Equals("CRJ1005")) // 会话失效
            {
                if (Login())
                {
                    mReturn = CallUnimethod(funcSavePhoto, jsonData, true);
                }
                else
                {
                    _strMessage = string.Format("上传制证相片发生了错误。 \n详情:{0}", _strMessage);
                    Log.WriteAsync(_strMessage);
                    return false;
                }
            }
            if (!mReturn.CallSuccessed)
            {
                _strMessage = string.Format("上传制证相片发生了错误。 \n详情:{0}", mReturn.ExceptionString);
                Log.WriteAsync(_strMessage);
                return false;
            }
            if (!mReturn.Success)
            {
                _strMessage = string.Format("上传制证相片失败! \n错误代码:{0}, 异常详情:{1}",
                     mReturn.ErrorCode,
                     mReturn.Message);
                Log.WriteAsync(_strMessage);
                return false;
            }
            _strMessage = string.Format("照片[{0}]上传成功: {1}", args.xpbh, mReturn.Message);
            Log.WriteAsync(_strMessage);
            return true;
        }

       
    }
}
